

from rest_framework import serializers
from . import models
from course.models import Course
from rest_framework.exceptions import ValidationError
from django.conf import settings

class OrderSerializer(serializers.ModelSerializer):
    '''
    订单：前端传数据的格式：{course:[1,2,3], total_amount:100, subject:xx商品， pay_type:1}
    还需要user对象，但是不是前端传过来的，使用了jwt
    需要把course:[1,2,3]处理成 course:[obj1, obj2, obj3] #通过课程对象，可以方便获取课程对应的信息
    同样课时也需要处理成obj 对象
    课时：[1,4,6] ===>课时：[obj1, obj4, obj6]
    '''
    #把course:[1,2,3]处理成 course:[obj1, obj2, obj3]
    course = serializers.PrimaryKeyRelatedField(queryset=Course.objects.all(), write_only=True, many=True) #一个订单可以有多个课程

    class Meta:
        model = models.Order
        fields = ['total_amount', 'subject', 'pay_type', 'course']
        extra_kwargs = {
            'total_amount':{'required':True},
            'pay_type':{'required':True}
        }
    def _check_price(self,attrs):
        total_amount = attrs.get('total_amount')
        course_list = attrs.get('course') #[1,2,3]
        total_price= 0 #总价格
        for course in course_list:
            total_price += course.price
        if total_price != total_amount:
            raise ValidationError('价格不合法')
        return total_amount

    def _get_out_trade_no(self):
        import uuid
        return str(uuid.uuid4()).replace('-', '')

    def _get_user(self):
        #要想拿到用户对象，需要request,但是这里没有，所有需要在调用序列化类时传入request
        #需要通过 context把request对象传入
        user = self.context.get('request').user
        return user

    def _get_pay_url(self,out_trade_no,total_amount, subject):

        from luffy.libs.aipay import alipay,gateway
        #订单生成
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=out_trade_no,
            total_amount=float(total_amount), #total_amout是Decimal类型，支付宝识别不了，需要转换为 float 类型
            subject=subject,
            return_url=settings.RETURN_URL,  # get回调，前台地址
            notify_url=settings.NOTIFY_URL  # post回调，后台地址
        )

        return gateway+order_string  #返回支付链接

    def _before_create(self,attrs, user, pay_url, out_trade_no):
        '''入库需要的准备'''
        attrs['user'] =user #订单表需要
        attrs['out_trade_no'] =out_trade_no
        self.context['pay_url'] =pay_url #为了可以在视图中拿到

    def validate(self, attrs):
        '''
        1 订单总价校验
        2 生成订单号
        3 拿到支付用户 request.user
        4 生成支付链接
        5 入库(两个表)的信息准备
        '''
        #1 订单总价校验
        total_amount = self._check_price(attrs)
        #2 生成订单号
        out_trade_no = self._get_out_trade_no()
        #3 支付用户
        user = self._get_user()

        #4 生成支付连接
        pay_url = self._get_pay_url(out_trade_no, total_amount, attrs.get('subject'))
        #5 入库(两个表)的信息准备
        self._before_create(attrs, user, pay_url, out_trade_no)
        return attrs

    #入库(操作两张表:订单表，订单详情表)
    def create(self, validated_data):
        #1 操作订单表
        #因为订单表是没有 course字段的，所以需要把course剔出
        course_list = validated_data.pop('course')
        order = models.Order.objects.create(**validated_data)
        #2 操作订单详情表
        #因为一个订单可能有多个课程，所有在订单详情表中应该有多条数据
        for course in course_list:
            models.OrderDetail.objects.create(order=order, course=course,price=course.price,real_price=course.price)
        return order